package com.example.teaching_server.service;

import com.example.teaching_server.dto.UserCheckinRequest;
import com.example.teaching_server.entity.ActivityCheckinEntity;
import com.example.teaching_server.entity.ActivityCheckinImageEntity;
import com.example.teaching_server.entity.ActivityEntity;
import com.example.teaching_server.repository.ActivityCheckinRepository;
import com.example.teaching_server.repository.ActivityRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户打卡服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class UserCheckinService {

    private final ActivityRepository activityRepository;
    private final ActivityCheckinRepository checkinRepository;

    /**
     * 用户打卡
     */
    public ActivityCheckinEntity checkin(Long activityId, UserCheckinRequest request) {
        log.info("用户打卡: activityId={}, userId={}", activityId, request.getUserId());

        validateCheckinRequest(activityId, request);

        ActivityEntity activity = getActivityById(activityId);
        validateActivityDateRange(activity);

        LocalDate today = LocalDate.now();
        validateDuplicateCheckin(request.getUserId(), activityId, today);

        ActivityCheckinEntity checkin = createCheckinEntity(activity, request, today);
        ActivityCheckinEntity savedCheckin = saveCheckinRecord(checkin);

        log.info("打卡成功: checkinId={}, activityId={}, userId={}",
                savedCheckin.getId(), activityId, request.getUserId());

        return savedCheckin;
    }

    /**
     * 验证打卡请求
     */
    private void validateCheckinRequest(Long activityId, UserCheckinRequest request) {
        if (activityId == null || activityId <= 0) {
            throw new IllegalArgumentException("活动ID无效");
        }
        if (request == null) {
            throw new IllegalArgumentException("打卡请求不能为空");
        }
        if (request.getUserId() == null || request.getUserId() <= 0) {
            throw new IllegalArgumentException("用户ID无效");
        }
    }

    /**
     * 根据ID获取活动
     */
    private ActivityEntity getActivityById(Long activityId) {
        return activityRepository.findById(activityId)
                .orElseThrow(() -> {
                    log.warn("活动不存在: activityId={}", activityId);
                    return new RuntimeException("活动不存在");
                });
    }

    /**
     * 验证活动日期范围
     */
    private void validateActivityDateRange(ActivityEntity activity) {
        LocalDate today = LocalDate.now();

        if (activity.getStartDate() != null && today.isBefore(activity.getStartDate())) {
            throw new RuntimeException("活动尚未开始");
        }

        if (activity.getEndDate() != null && today.isAfter(activity.getEndDate())) {
            throw new RuntimeException("活动已结束");
        }
    }

    /**
     * 验证重复打卡
     */
    private void validateDuplicateCheckin(Long userId, Long activityId, LocalDate checkDate) {
        boolean hasChecked = checkinRepository.existsByUserIdAndActivityIdAndCheckDate(
                userId, activityId, checkDate);

        if (hasChecked) {
            log.warn("重复打卡: userId={}, activityId={}, date={}", userId, activityId, checkDate);
            throw new RuntimeException("今日已打卡，不能重复打卡");
        }
    }

    /**
     * 创建打卡实体
     */
    private ActivityCheckinEntity createCheckinEntity(ActivityEntity activity, UserCheckinRequest request, LocalDate checkDate) {
        ActivityCheckinEntity checkin = new ActivityCheckinEntity();
        checkin.setActivity(activity);
        checkin.setUserId(request.getUserId());
        checkin.setCheckDate(checkDate);
        checkin.setCheckTime(LocalTime.now());
        checkin.setDescription(request.getDescription());
        checkin.setCreatedAt(LocalDateTime.now());
        return checkin;
    }

    /**
     * 保存打卡记录
     */
    private ActivityCheckinEntity saveCheckinRecord(ActivityCheckinEntity checkin) {
        return checkinRepository.save(checkin);
    }

    /**
     * 获取用户打卡记录（使用现有的方法）
     */
    @Transactional(readOnly = true)
    public List<ActivityCheckinEntity> getUserCheckins(Long userId, Long activityId) {
        log.debug("获取用户打卡记录: userId={}, activityId={}", userId, activityId);

        validateUserId(userId);
        validateActivityId(activityId);

        return checkinRepository.findByUserIdAndActivityId(userId, activityId);
    }

    /**
     * 获取用户某天所有打卡记录
     */
    @Transactional(readOnly = true)
    public List<ActivityCheckinEntity> getUserCheckinsByDate(Long userId, LocalDate date) {
        log.debug("获取用户日期打卡记录: userId={}, date={}", userId, date);

        validateUserId(userId);
        validateDate(date);

        return checkinRepository.findByUserIdAndDate(userId, date);
    }

    /**
     * 获取活动打卡统计（基于现有方法实现）
     */
    @Transactional(readOnly = true)
    public CheckinStatistics getActivityCheckinStatistics(Long activityId) {
        log.debug("获取活动打卡统计: activityId={}", activityId);

        validateActivityId(activityId);

        // 获取所有参与该活动的用户ID
        List<Long> userIds = checkinRepository.findJoinedActivityIds(activityId);

        if (userIds.isEmpty()) {
            return new CheckinStatistics(0, 0);
        }

        // 统计每个用户的打卡记录
        int totalCheckins = 0;
        int uniqueUsers = 0;

        for (Long userId : userIds) {
            List<ActivityCheckinEntity> userCheckins = checkinRepository.findByUserIdAndActivityId(userId, activityId);
            if (!userCheckins.isEmpty()) {
                totalCheckins += userCheckins.size();
                uniqueUsers++;
            }
        }

        return new CheckinStatistics(totalCheckins, uniqueUsers);
    }

    /**
     * 获取用户活动打卡天数统计
     */
    @Transactional(readOnly = true)
    public int getUserActivityCheckinDays(Long userId, Long activityId) {
        log.debug("获取用户活动打卡天数: userId={}, activityId={}", userId, activityId);

        validateUserId(userId);
        validateActivityId(activityId);

        List<ActivityCheckinEntity> checkins = checkinRepository.findByUserIdAndActivityId(userId, activityId);
        return (int) checkins.stream()
                .map(ActivityCheckinEntity::getCheckDate)
                .distinct()
                .count();
    }

    /**
     * 验证用户ID
     */
    private void validateUserId(Long userId) {
        if (userId == null || userId <= 0) {
            throw new IllegalArgumentException("用户ID无效");
        }
    }

    /**
     * 验证活动ID
     */
    private void validateActivityId(Long activityId) {
        if (activityId == null || activityId <= 0) {
            throw new IllegalArgumentException("活动ID无效");
        }
    }

    /**
     * 验证日期
     */
    private void validateDate(LocalDate date) {
        if (date == null) {
            throw new IllegalArgumentException("日期不能为空");
        }
    }

    /**
     * 打卡统计信息内部类
     */
    public static class CheckinStatistics {
        private final int totalCheckins;
        private final int uniqueUsers;

        public CheckinStatistics(int totalCheckins, int uniqueUsers) {
            this.totalCheckins = totalCheckins;
            this.uniqueUsers = uniqueUsers;
        }

        public int getTotalCheckins() { return totalCheckins; }
        public int getUniqueUsers() { return uniqueUsers; }
    }

    /**
     * 检查用户是否已打卡
     */
    @Transactional(readOnly = true)
    public boolean hasUserCheckedIn(Long userId, Long activityId, LocalDate date) {
        log.debug("检查用户打卡状态: userId={}, activityId={}, date={}", userId, activityId, date);

        validateUserId(userId);
        validateActivityId(activityId);
        validateDate(date);

        return checkinRepository.existsByUserIdAndActivityIdAndCheckDate(userId, activityId, date);
    }

    /**
     * 获取用户最近的打卡记录
     */
    @Transactional(readOnly = true)
    public ActivityCheckinEntity getLatestUserCheckin(Long userId, Long activityId) {
        log.debug("获取用户最近打卡记录: userId={}, activityId={}", userId, activityId);

        validateUserId(userId);
        validateActivityId(activityId);

        List<ActivityCheckinEntity> checkins = checkinRepository.findByUserIdAndActivityId(userId, activityId);
        if (checkins.isEmpty()) {
            return null;
        }

        // 按日期降序排序，返回最新的打卡记录
        return checkins.stream()
                .sorted((c1, c2) -> c2.getCheckDate().compareTo(c1.getCheckDate()))
                .findFirst()
                .orElse(null);
    }
}
